//
//  AudioFileIOManager_MACOSX.cpp
//  LowPassFilter_Standalone
//
//  Created by kadlubek47 on 13.03.2013.
//  Copyright (c) 2013 kadlubek47. All rights reserved.
//

#include "AudioFileIOManager_MACOSX.h"
#include <iostream>

AudioFileIOManager_MACOSX::AudioFileIOManager_MACOSX() {}
AudioFileIOManager_MACOSX::~AudioFileIOManager_MACOSX() {}

void AudioFileIOManager_MACOSX::read(const char* pathToFile, int bytePerSample, long long int* length /*out*/, void*** channels /*out*/, int* numOfChannels /*out*/, unsigned int* samplingRate /*out*/) {
    CFStringRef urlString = CFStringCreateWithCString(NULL, pathToFile, kCFStringEncodingASCII);
    CFURLRef inURL = CFURLCreateWithString(NULL, urlString, NULL);
    
    OSStatus code;
    code = ExtAudioFileOpenURL(inURL, &inFileReference_);
    
    getFileDescription();
    setConvertingBufferParameters(bytePerSample);
    readFileIntoBuffer();
    getAudio(length, channels, numOfChannels);
    
    *samplingRate = inFileDescription_.mSampleRate;
}

void AudioFileIOManager_MACOSX::write(void** channels, const char* pathToNewFile) {
    setAudio(channels);
    setConvertingOutFileParameters();
    
    OSStatus code;
    
    ExtAudioFileRef refToNewAudioFIle;
    CFStringRef newUrlString = CFStringCreateWithCString(NULL, pathToNewFile, kCFStringEncodingASCII);
    CFURLRef newInURL = CFURLCreateWithString(NULL, newUrlString, NULL);
    
    code = ExtAudioFileCreateWithURL(newInURL, kAudioFileWAVEType, &outFileDescription_, NULL, 0, &refToNewAudioFIle);
    
    code = ExtAudioFileWrite(refToNewAudioFIle, numberFramesRead_, &outFileBuffer_);
    ExtAudioFileDispose(refToNewAudioFIle);
    
    //free
}

//-------------------------------------------------------------------------------------------------------------------------

void AudioFileIOManager_MACOSX::getFileDescription() {
    OSStatus code;
    UInt32 outSize;
    
    //basic description
    outSize=sizeof(AudioStreamBasicDescription);
    code = ExtAudioFileGetProperty(inFileReference_, kExtAudioFileProperty_FileDataFormat, &outSize, &inFileDescription_);
    
    //length of file
    outSize=sizeof(SInt64);
    code = ExtAudioFileGetProperty(inFileReference_, kExtAudioFileProperty_FileLengthFrames, &outSize, &inFileLength_);
    
    //AudioFileTypeID
    AudioFileTypeID audioFileTypeID;;
    outSize=sizeof(AudioFileTypeID);
    code = ExtAudioFileGetProperty(inFileReference_, kExtAudioFileProperty_AudioFile, &outSize, &audioFileTypeID);
    
    //AudioChannelLayout
    AudioChannelLayout audioChannelLayout;
    outSize=sizeof(AudioChannelLayout);
    code = ExtAudioFileGetProperty(inFileReference_, kExtAudioFileProperty_ClientChannelLayout, &outSize, &audioChannelLayout);
}

void AudioFileIOManager_MACOSX::setConvertingBufferParameters(int bytePerSample) {
    bufferDescription_=inFileDescription_;
    bufferDescription_.mFormatFlags=kAudioFormatFlagsNativeFloatPacked;
    bufferDescription_.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
    bufferDescription_.mBitsPerChannel=bytePerSample*8;
    bufferDescription_.mBytesPerFrame=bufferDescription_.mBytesPerPacket=bytePerSample;
    ExtAudioFileSetProperty(inFileReference_, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &bufferDescription_);
}

void AudioFileIOManager_MACOSX::readFileIntoBuffer() {
    OSStatus code;
    
    numberFramesRead_=inFileLength_;
    UInt32 bytesPerChannel=bufferDescription_.mBitsPerChannel/8;
    
    inFileBuffer_.mNumberBuffers = 1;
    inFileBuffer_.mBuffers[0].mNumberChannels = bufferDescription_.mChannelsPerFrame;
    inFileBuffer_.mBuffers[0].mDataByteSize = bytesPerChannel * numberFramesRead_;
    void* dt = malloc( (bytesPerChannel) * numberFramesRead_  );
    inFileBuffer_.mBuffers[0].mData = dt;
    
    code = ExtAudioFileRead (inFileReference_, &numberFramesRead_, &inFileBuffer_);
}

void AudioFileIOManager_MACOSX::getAudio(long long int* length /*out*/, void*** channels /*out*/, int* numberOfChannels /*out*/) {
    *length=inFileLength_;
    *numberOfChannels=inFileBuffer_.mNumberBuffers;
    *channels=new void*[*numberOfChannels];
    for(int i=0; i<*numberOfChannels; ++i) {
        (*channels)[i]=inFileBuffer_.mBuffers[i].mData;
    }
}

void AudioFileIOManager_MACOSX::setAudio(void** channels) {
    outFileBuffer_.mNumberBuffers = 1;
    outFileBuffer_.mBuffers[0].mNumberChannels = bufferDescription_.mChannelsPerFrame;
    outFileBuffer_.mBuffers[0].mDataByteSize = bufferDescription_.mBitsPerChannel/8 * numberFramesRead_;
    for(int i=0; i < inFileBuffer_.mNumberBuffers ; ++i) {
        outFileBuffer_.mBuffers[i].mData = channels[i];
    }
}

void AudioFileIOManager_MACOSX::setConvertingOutFileParameters(){
    outFileDescription_=bufferDescription_;
}

void AudioFileIOManager_MACOSX::printDescription(AudioStreamBasicDescription descr) {
    std::cout<<"SampleRate="<<descr.mSampleRate << std::endl;
    std::cout<<"ChannelsPerFrame="<<descr.mChannelsPerFrame << std::endl;
    std::cout<<"BitsPerChannel="<<descr.mBitsPerChannel << std::endl;
}